home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Think Class Libraries / Item Class / Item sources / CItemTable.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-30  |  22.3 KB  |  1,072 lines  |  [TEXT/KAHL]

  1. /*
  2.  * File:        CItemTable.c
  3.  * Created:        7/25/93
  4.  * Desc:        
  5.  *
  6.  * Superclass:    CArrayPane.
  7.  * Uses:        CItem.
  8.  * Original Author:    Atul Barve
  9.  * Modifications:    W. Wesley Monroe
  10.  *
  11.  * Copyright © 1993 Animas Software Production. All rights reserved.
  12.  */
  13.  
  14. #include <TBUtilities.h>
  15. #include <Icons.h>
  16. #include <ctype.h>
  17.  
  18. #include "CTypingTask.h"
  19. #include "CItemTable.h"
  20. #include "CItemList.h"
  21. #include "CItem.h"
  22. #include "CTableExpander.h"
  23. #include "CDragDropTableTask.h"
  24. #include "CExtendDragTask.h"
  25. #include    <Constants.h>
  26.  
  27. #include    <Sound.h>
  28.  
  29.  
  30. #define    kCellFont            monaco
  31. #define    kCellFontSize        9
  32. #define    kCellFontStyle        0
  33. #define    kCellLevelIndent    16
  34. #define    kIconWidth            16
  35. #define    kIconHeight            16
  36. #define    kCellHeight            20
  37. #define    kIconIndent            20
  38. #define    kTextIndent            40
  39. #define deleteKey            '\b'
  40.  
  41. #define    kOpenTriangle        133
  42. #define    kCloseTriangle        131
  43. #define    kInterimTriangle    132
  44.  
  45. extern RgnHandle    gUtilRgn;
  46.  
  47. /*
  48.  * IItemTable
  49.  */
  50. #define IsRectRgn(rgn)    \
  51.     ((rgn) && ((**rgn).rgnSize == sizeof(Region)) && !EmptyRgn( rgn))
  52.  
  53. void CItemTable::IItemTable( CView *anEnclosure, CBureaucrat *aSupervisor,
  54.                         short aWidth, short aHeight,
  55.                         short aHEncl, short aVEncl,
  56.                         SizingOption aHSizing, SizingOption aVSizing,
  57.                         short dragFlag)
  58. {
  59.     CArrayPane::IArrayPane( anEnclosure, aSupervisor, aWidth, aHeight,
  60.                     aHEncl, aVEncl, aHSizing, aVSizing);
  61.  
  62.     fSelItems = new CItemList;
  63.     fSelItems->IItemList();
  64.     
  65.     SetDefaults( -1, kCellHeight);
  66.  
  67.     fDragFlag = dragFlag;
  68. }
  69.  
  70. void CItemTable::IViewTemp( CView *anEnclosure, CBureaucrat *aSupervisor,Ptr viewData)
  71. {
  72.     LongRect    r;
  73.     CArrayPane::IViewTemp( anEnclosure, aSupervisor, viewData);
  74.  
  75.     fSelItems = new CItemList;
  76.     fSelItems->IItemList();
  77.     r = frame;
  78.     SetBounds(&r);
  79.     
  80. }
  81.  
  82. void    CItemTable::SetDragFlag(short flag)
  83. {
  84.     fDragFlag = flag;
  85. }
  86.  
  87. /*
  88.  * GetCellText() {OVERRIDE}
  89.  *
  90.  *    Return the cell text from the CItem in a Pascal String
  91.  */
  92.  
  93. void CItemTable::GetCellText( Cell aCell, short availableWidth, StringPtr itsText)
  94. {
  95.     CItemList    *list;
  96.     CItem        *aItem;
  97.  
  98.     ASSERT( member( itsArray, CItemList));
  99.  
  100.     if (itsArray)
  101.     {
  102.         list = (CItemList *) itsArray;
  103.         aItem = (CItem*) list->NthItem( aCell.v+1);
  104.         if(aItem) {
  105.             aItem->GetDisplayText((char*)itsText);
  106.         }
  107.     }
  108.  
  109. }
  110.  
  111. enum {
  112.     kArrowCollapsed = 131,
  113.     kArrowTransition,
  114.     kArrowExpanded
  115. };
  116.  
  117. void    CItemTable::AnimateOpenClose(Cell hitCell)
  118. {
  119.     LongRect    pinRect;
  120.     Rect        iconRect;
  121.     short        indentLeft;
  122.     CItem        *aItem;
  123.     short        expanded;
  124.     short        ic1,ic2,ic3;
  125.     long        ts;
  126.     
  127.     aItem = GetItem(hitCell.v + 1);
  128.  
  129.     if(aItem) {
  130.         GetCellRect(hitCell,&pinRect);
  131.  
  132.         expanded = aItem->GetExpanded();
  133.  
  134.         iconRect.bottom = iconRect.top = (pinRect.bottom + pinRect.top) / 2 - 8;
  135.         iconRect.right = iconRect.left = pinRect.left + indent.h;
  136.         iconRect.right += 16;
  137.         iconRect.bottom += 16;
  138.  
  139.         expanded = aItem->GetExpanded();
  140.         if(expanded) {
  141.             ic1 = kArrowCollapsed;
  142.             ic3 = kArrowExpanded;
  143.         }
  144.         else {
  145.             ic3 = kArrowCollapsed;
  146.             ic1 = kArrowExpanded;
  147.         }
  148.  
  149.         Prepare();
  150.         EraseRect(&iconRect);
  151.         ic2 = kArrowTransition;
  152.         DrawTriangle(&iconRect, 0, ic1);
  153.         ts = TickCount();
  154.         while(ts + 5 > TickCount());
  155.         DrawTriangle(&iconRect, 0, ic2);
  156.         ts = TickCount();
  157.         while(ts + 5 > TickCount());
  158.         DrawTriangle(&iconRect, 0, ic3);
  159.     }
  160. }
  161.  
  162. void    CItemTable::DrawTriangle(Rect *cellRect,short indentLeft,short id)
  163. {
  164.     EraseRect(cellRect);
  165.     Draw7Icon(cellRect,indentLeft,id,ttNone);
  166. }
  167.  
  168. /*
  169.  * GetCanRecieve()
  170.  *
  171.  *    Can the table recieve dropped objects?
  172.  */
  173.  
  174. Boolean CItemTable::GetCanRecieve(void)
  175. {
  176.     return selectionFlags & selCanRecieve;
  177. }
  178.  
  179. /*
  180.  * Draw7Icon()
  181.  *
  182.  *    Draw the Item icon centered in the middle of the cell.
  183.  */
  184.  
  185. void CItemTable::Draw7Icon(Rect *cellRect, short indentLeft,
  186.                            short id, short xfer)
  187. {
  188.     short        mid;
  189.     Rect        iRect;
  190.     CIconHandle    hndl;
  191.     Handle        iSuite = 0;
  192.  
  193.  
  194.     mid = (cellRect->bottom + cellRect->top) / 2;
  195.     
  196.     iRect.top = mid - 8;
  197.     iRect.bottom = iRect.top + 16;
  198.     iRect.left = indent.h + indentLeft;
  199.     iRect.right = iRect.left + 16;
  200.  
  201.     PlotIconID(&iRect, atNone, xfer, id);
  202. }
  203.  
  204. /*
  205.  * DrawCell()
  206.  *
  207.  *    Draw:
  208.  *        - the expando icon if its a parent cell
  209.  *        - the item icon if it has one
  210.  *        - the text of the item
  211.  */
  212.  
  213. void CItemTable::DrawCell( Cell theCell, Rect *cellRect)
  214. {
  215.     Str255        cellText;
  216.     short        availWidth;
  217.     CItem        *aItem;
  218.     CItemList    *list;
  219.     short        levelIndent;
  220.     short        numSubs;
  221.     short        y;
  222.     
  223.     ASSERT(member(itsArray,CItemList));
  224.     
  225.     list = (CItemList*) itsArray;
  226.  
  227.     aItem = (CItem*) list->NthItem(theCell.v + 1);
  228.     
  229.     ASSERT(aItem);
  230.     
  231.     levelIndent = aItem->GetLevel() * kCellLevelIndent;
  232.  
  233.     numSubs = aItem->GetNumSubItems();
  234.  
  235.     availWidth = cellRect->right - cellRect->left - indent.h;
  236.  
  237.     
  238.     GetCellText( theCell, availWidth, cellText);
  239.  
  240.     y = ((cellRect->bottom - cellRect->top) - ( fontInfo.ascent)) / 2;
  241.     if (cellText[0] > 0)
  242.     {
  243.         if(aItem && aItem->GetExpanded() && numSubs)
  244.             Draw7Icon(cellRect, 0,kOpenTriangle, ttNone);
  245.         else if(aItem && numSubs)
  246.             Draw7Icon(cellRect, 0,kCloseTriangle, ttNone);
  247.  
  248.         Draw7Icon(cellRect, levelIndent + kIconIndent, aItem->GetIconID(), ttNone);
  249.         MoveTo( cellRect->left + indent.h + levelIndent + kTextIndent, cellRect->bottom - y);
  250.         DrawString( cellText);
  251.     }
  252. }
  253.  
  254. /*
  255.  * ExpandCell()
  256.  *
  257.  *    Expand or Close a parent item.
  258.  */
  259.  
  260. void CItemTable::ExpandCell(Cell theCell,short expand)
  261. {
  262.     CItem        *aItem,*sub,*pSub;
  263.     CItemList    *list;
  264.     short        numSubViews;
  265.     short        i;
  266.     Handle        sndHndl;
  267.     
  268.     ASSERT(member(itsArray,CItemList));
  269.     
  270.     list = (CItemList*) itsArray;
  271.     
  272.     aItem = (CItem*)list->NthItem(theCell.v + 1);
  273.     
  274.     ASSERT(aItem);
  275.     
  276.     numSubViews = aItem->GetNumSubItems();
  277.     pSub = aItem;
  278.     
  279.     sndHndl = Get1Resource('snd ',128);
  280.     if(sndHndl)
  281.         SndPlay(0,sndHndl,0);
  282.     for(i=1;i<=numSubViews;i++) {
  283.         sub = aItem->GetNthSubItem(i);
  284.         if(expand) {
  285.             list->InsertAfter(sub,pSub);
  286.             pSub = sub;
  287.         }
  288.         else {
  289.             list->RemoveFromVisTree(sub);
  290.             pSub = sub;
  291.         }
  292.     }
  293.  
  294.     BroadcastChange(itemTableItemExpanded, aItem);
  295. }
  296.  
  297. /*
  298.  * RemoveSubviews()
  299.  *
  300.  *    Delete references to the selectedItems in the
  301.  *    parents subview list.
  302.  */
  303.  
  304. void CItemTable::RemoveSubviews(CItemList *selectedItems)
  305. {
  306.     CItem    *itemToRemove, *parent;
  307.     short    i, nItems = selectedItems->GetNumItems();
  308.     long    ndx;
  309.  
  310.     for(i = 1; i <= nItems; i++) {
  311.         
  312.         itemToRemove = (CItem *) selectedItems->NthItem(i);
  313.  
  314.         parent = itemToRemove->GetParent();
  315.         if(parent)
  316.             parent->RemoveSubItem(itemToRemove);
  317.  
  318.             // Remove items from what is visible
  319.             // on the screen...
  320.         ((CItemList *) itsArray)->RemoveFromVisTree(itemToRemove);
  321.  
  322.     }
  323. }
  324.  
  325. void CItemTable::GraftItems(CItem *parent, CItemList *selectedItems)
  326. {
  327.     CItem    *itemToGraft;
  328.  
  329.     short i, nItems = selectedItems->GetNumItems();
  330.  
  331.     for(i = 1; i <= nItems; i++) {
  332.         
  333.         itemToGraft = (CItem *) selectedItems->NthItem(i);
  334.  
  335.                 // Set the new daddy...
  336.         if(parent) {
  337.     
  338.             itemToGraft->SetParent(parent);
  339. //            itemToGraft->SetLevel(parent->GetLevel() + 1);
  340.             itemToGraft->SetExpanded(parent->GetExpanded());
  341.             parent->GraftSubItem(itemToGraft);
  342.     
  343.                 // now put it in the visible list...
  344.             if(parent->GetExpanded()) {
  345.                 Cell pCell = {0, 0};
  346.                 
  347.                 pCell.v = ((CItemList *) itsArray)->Offset(parent);
  348.                 ExpandCell(pCell, FALSE);
  349.                 ExpandCell(pCell, TRUE);
  350.             }
  351.             BroadcastChange(itemTableItemAdded, itemToGraft);
  352.         } else
  353.             AddItemToRoot(itemToGraft);        
  354.     
  355.     }
  356.     Refresh();
  357. }
  358.  
  359. void CItemTable::AddItemToRoot(CItem *itemToGraft)
  360. {
  361.     itemToGraft->SetParent(0L);
  362.     itemToGraft->SetLevel(0);
  363.     itemToGraft->SetExpanded(FALSE);
  364.     
  365.     ((CItemList *) itsArray)->Append(itemToGraft);
  366.     BroadcastChange(itemTableItemAdded, itemToGraft);
  367. }
  368.  
  369. /*
  370.  * MakeMouseTask()
  371.  *
  372.  *    Return the appropriate type of task depending
  373.  *  on if the user selected in the expand icon
  374.  *  or the item itself.
  375.  */
  376.  
  377. CMouseTask *CItemTable::MakeMouseTask(short modifiers)
  378. {
  379.     CTableExpander        *tblTask;
  380.     CDragDropTableTask    *tblTask2;
  381.     CTableDragger        *tblTask3;
  382.     CItem            *aItem;
  383.     CItemList        *list;
  384.     
  385.     LongPt            pt;
  386.     LongRect        pinRect;
  387.     Point            hitPt;
  388.     Rect            iRect;
  389.     Cell            hitCell;
  390.     short            expanded, indentLeft, inOut, numSubs;
  391.     Rect            draggingRect;
  392.     Rect            iconRect,textRect,triRect;
  393.     char            text[256];
  394.     short            canExpand;
  395.     CExtendDragTask    *tblTask4;
  396.     
  397.     GetMouse(&hitPt);
  398.     QDToFrame(hitPt, &pt);
  399.  
  400.     ASSERT(member(itsArray,CItemList));
  401.     
  402.     list = (CItemList *) itsArray;
  403.  
  404.     tblTask = NULL;
  405.  
  406.     if(PtInLongRect( &pt, &bounds))
  407.     {
  408.         FindHitCell( &pt, &hitCell);
  409.  
  410.         GetCellRect(hitCell,&pinRect);
  411.  
  412.         aItem = (CItem*)list->NthItem(hitCell.v + 1);
  413.         ASSERT(aItem);
  414.         expanded = aItem->GetExpanded();
  415.         indentLeft =  aItem->GetLevel()*kCellLevelIndent;
  416.  
  417.         iRect.bottom = iRect.top = (pinRect.bottom + pinRect.top) / 2 - 8;
  418. //        iRect.right = iRect.left = pinRect.left + indent.h + indentLeft;
  419.         iRect.right = iRect.left = pinRect.left + indent.h;
  420.         iRect.right += 16;
  421.         iRect.bottom += 16;
  422.  
  423.         iconRect = iRect;
  424.         iconRect.left += kIconIndent;
  425.         iconRect.right = iconRect.left + kIconWidth;
  426.         
  427.         textRect = iRect;
  428.  
  429.         textRect.left += kTextIndent;
  430.         aItem->GetDisplayText(text);
  431.         textRect.right = textRect.left + StringWidth(text);
  432.         
  433.         triRect = iRect;
  434.         
  435.         
  436.         
  437.         numSubs = aItem->GetNumSubItems();        
  438.         inOut = PtInRect(hitPt, &iRect);
  439.         canExpand = inOut && numSubs;
  440.  
  441.         if(PtInRect(hitPt,&textRect) == 0 && 
  442.            PtInRect(hitPt,&iconRect) == 0 && 
  443.            canExpand == 0 ) {
  444.             CView    *mainView;
  445.             
  446.  
  447.             mainView = itsEnclosure;
  448.             tblTask4 = new CExtendDragTask;
  449.             tblTask4->IExtendDragTask(this, mainView, modifiers, selectionFlags);
  450.             return tblTask4;
  451.  
  452.         }
  453.         else if(inOut == 0 || numSubs == 0) {
  454.             CView    *mainView;
  455.  
  456.             if(!(selectionFlags & selCanDrag))
  457.                 return inherited::MakeMouseTask(modifiers);
  458.  
  459.             mainView = itsEnclosure;
  460.             tblTask2 = new CDragDropTableTask;
  461.             tblTask2->IDragDropTableTask(this, mainView, modifiers, selectionFlags);
  462.             return tblTask2;
  463.         }
  464.         else {
  465.             tblTask = new CTableExpander;
  466.             tblTask->ITableExpander(this, modifiers, selectionFlags,
  467.                                     aItem, iRect);
  468.             return tblTask;
  469.         }
  470.     }
  471.     return 0;
  472. }    /* CItemTable::MakeMouseTask */
  473.  
  474. /*
  475.  * GetItem()
  476.  *
  477.  *    Return the item in row,
  478.  *    NOTE:    row is a 1 based index!!!!
  479.  */
  480.  
  481. CItem    *CItemTable::GetItem(short row)
  482. {
  483.     CItemList    *list;
  484.     CItem        *aItem;
  485.     
  486.     if(itsArray == 0)
  487.         return 0;
  488.  
  489.     ASSERT(member(itsArray,CItemList));
  490.     
  491.     list = (CItemList*) itsArray;
  492.     
  493.     aItem = (CItem*)list->NthItem(row);
  494.     return aItem;
  495. }
  496.  
  497. /*
  498.  * TrackMouse() {OVERRIDE}
  499.  *
  500.  *    Reset the clipRect to the window rect so that
  501.  *    the gray region can be moved outside the window region
  502.  */
  503.  
  504. void CItemTable::TrackMouse(CMouseTask *theTask, LongPt *startPt,
  505.                             LongRect *pinRect)
  506. {
  507.     LongPt        currPt;
  508.     LongPt        prevPt;
  509.  
  510.     EventRecord    macEvent;
  511.     Point        qdPt;
  512.     Rect        clipR;
  513.     Boolean        doClip;
  514.  
  515.     clipR = macPort->portRect;
  516.  
  517.     Prepare();
  518.  
  519.     doClip = (selectionFlags & selCanDrag) || (selectionFlags & selCanRecieve) &&
  520.                 (fDragFlag != kDragInPaneOnly);
  521.     if(doClip)
  522.         ClipRect(&clipR);
  523.     
  524.     theTask->BeginTracking( startPt);
  525.     currPt = prevPt = *startPt;
  526.  
  527.     while (StillDown()) {                /* Track while button is pressed    */
  528.     
  529.                                         /* ??? We could call WaitNextEvent    */
  530.                                         /*   here to give background apps    */
  531.                                         /*   some CPU time. However, this    */
  532.                                         /*   makes mouse tracking a little    */
  533.                                         /*   bit sluggish.                    */
  534.         Prepare();
  535.         if(doClip)
  536.             ClipRect(&clipR);
  537.         
  538.         GetMouse(&qdPt);
  539.         QDToFrame( qdPt, &currPt);
  540.  
  541.         if(!doClip)            
  542.             PinInRect(pinRect, &currPt);
  543.         else {
  544.             QDToLongRect(&clipR, pinRect);
  545.             PinInRect(pinRect, &currPt);
  546.         }
  547.  
  548.         theTask->KeepTracking( &currPt, &prevPt, startPt);
  549.         prevPt = currPt;
  550.     }
  551.     
  552.     Prepare();
  553.     if(doClip)
  554.         ClipRect(&clipR);
  555.  
  556.     if (OSEventAvail(mUpMask, &macEvent)) {
  557.         qdPt = macEvent.where;
  558.         GlobalToLocal(&qdPt);
  559.         QDToFrame( qdPt, &currPt);
  560.     }
  561.     
  562.     PinInRect( pinRect, &currPt);
  563.     theTask->EndTracking( &currPt, &prevPt, startPt);
  564. }
  565.  
  566. Boolean    CItemTable::HasSelection(void)
  567. {
  568.     return EmptyRgn(itsSelection);
  569. }
  570.  
  571. void CItemTable::Hilite( Rect *cells, Boolean hiliteFlag)
  572. {
  573.     LongRect    pixels;
  574.     Rect        visPixels;
  575.     CItem        *aItem;
  576.     short        indentLevel;
  577.     short        width;
  578.     char        text[256];
  579.     PenState    savePen;
  580.     CIconHandle    hndl;
  581.     RgnHandle    tmp;
  582.         
  583.     GetPenState(&savePen);
  584.     if (!printing)
  585.     {
  586.         CellsToPixels( cells, &pixels);    /* get the pixels spanning the cells    */
  587.         aItem = GetItem(cells->top + 1);
  588.         indentLevel = pixels.left;
  589.         if(aItem) {
  590.             aItem->GetDisplayText(text);
  591.             TextFont(kCellFont);
  592.             TextSize(kCellFontSize);
  593.             width = StringWidth(text);
  594.             indentLevel = aItem->GetLevel() * kCellLevelIndent;
  595.         }
  596. //        pixels.left = (pixels.left < indentLevel) ? indentLevel + 42 : pixels.left;
  597.         pixels.left = indentLevel + 42; // past the icon to the text;
  598.         if ( SectAperture( &pixels, &visPixels))
  599.         {
  600.             if(aItem) {
  601.                 if(hiliteFlag)
  602.                     Draw7Icon(&visPixels, indentLevel + 20, aItem->GetIconID(),
  603.                               ttSelected);
  604.                 else
  605.                     Draw7Icon(&visPixels, indentLevel + 20, aItem->GetIconID(),
  606.                               ttNone);
  607.             }
  608.  
  609.             PenPat(black);
  610. //            SetHiliteMode();
  611.             visPixels.right = visPixels.left + width;
  612.             InsetRect(&visPixels, 0, 2);
  613.             InvertRect( &visPixels);
  614.         }
  615.     }
  616.     SetPenState(&savePen);
  617. }
  618.  
  619. void CItemTable::Draw( Rect *area)
  620. {
  621.     Cell        topLeftCell, botRightCell, currCell;
  622.     short        i;
  623.     Rect        selectedCells, theCells;
  624.     LongRect     r;
  625.     Boolean        doCellHilite, reallyActive;
  626.             
  627.     QDToFrameR( area, &r);
  628.     
  629.     if (!SectLongRect( &r, &bounds, &r))
  630.         return;        
  631.     
  632.         /* account for topLeftIndent             */
  633.         
  634.     r.left = Max( r.left, topLeftIndent.h);
  635.     r.top = Max( r.top, topLeftIndent.v);    
  636.  
  637.     r.right--;
  638.     r.bottom--;
  639.         
  640.         /* find bounding cells of redraw rect     */
  641.         
  642.     FindHitCell( &topLeftL(r), &topLeftCell);
  643.     FindHitCell( &botRightL(r), &botRightCell);
  644.     
  645.     topLeft(theCells) = topLeftCell;
  646.     botRight( theCells) = botRightCell;
  647.     theCells.bottom++; theCells.right++;
  648.     DrawBorders( &theCells);
  649.  
  650.     reallyActive = IsActive();
  651.     doCellHilite = reallyActive && !IsRectRgn( itsSelection);
  652.     
  653.     FrameToQDR( &aperture, &qdClip);
  654.     
  655.     if (drawOrder == tblRow)
  656.     {
  657.         for ( i = topLeftCell.v; i <= botRightCell.v; i++)
  658.             DrawRow( i, topLeftCell.h, botRightCell.h, doCellHilite);
  659.     }
  660.     else if (drawOrder == tblCol)
  661.     {
  662.         for ( i = topLeftCell.h; i <= botRightCell.h; i++)
  663.             DrawCol( i, topLeftCell.v, botRightCell.v, doCellHilite);    
  664.     }
  665.  
  666.     if (clipToCells)
  667.     {
  668.         ForceNextPrepare();
  669.         Prepare();
  670.     }
  671.  
  672.     reallyActive = 1;
  673.  
  674.     if (reallyActive)
  675.     {
  676.         selectedCells = (**itsSelection).rgnBBox;
  677.         if (SectRect( &theCells, &selectedCells, &selectedCells)) {
  678.         
  679.             for (theCells.top = selectedCells.top; theCells.top < selectedCells.bottom; theCells.top++) {
  680.                 theCells.bottom = theCells.top + 1;
  681.                 for (theCells.left = selectedCells.left; theCells.left < selectedCells.right; theCells.left++) {
  682.                     theCells.right = theCells.left + 1;
  683.                     Hilite( &theCells, TRUE);    
  684.                 }
  685.             }
  686.         }
  687.     }
  688.     
  689.         
  690. }    /* CTable::Draw */
  691.  
  692. /*
  693.  * GetHiliteRgn()
  694.  *
  695.  *    Get the hilite region, and return a list with references to
  696.  *    the selected CItems.
  697.  */
  698.  
  699. CItemList *CItemTable::GetHiliteRgn(RgnHandle *rgnHdl)
  700. {
  701.     CItemList    *itemList;
  702.     CItem        *aItem;
  703.  
  704.     LongRect    pinRect;
  705.  
  706.     Rect        cellRect, r;
  707.     RgnHandle    cellRgn;
  708.     Cell        hitCell;
  709.     Rect        iconRect, cRect, iRect, bRect;
  710.  
  711.     short        indentLeft;
  712.     char        text[256];
  713.     
  714.     itemList = new CItemList;
  715.     itemList->IItemList();
  716.  
  717.     pinRect = bounds;
  718.  
  719.     LongToQDRect(&pinRect,&bRect);
  720.     
  721.     cellRgn = GetSelection();
  722.     *rgnHdl = NewRgn();
  723. //    fSelItems->Dispose();
  724.     if (!EmptyRgn( cellRgn)) {
  725.     
  726.         cellRect = (**cellRgn).rgnBBox;
  727.         OpenRgn();
  728.         
  729.         for (r.top = cellRect.top; r.top < cellRect.bottom; r.top++) {
  730.  
  731.             r.bottom = r.top + 1;
  732.             for (r.left = cellRect.left; r.left < cellRect.right; r.left++)
  733.             {
  734.                 r.right = r.left + 1;
  735.                 if (PtInRgn( topLeft( r), cellRgn)) {
  736.  
  737.                     aItem = GetItem(r.top + 1);
  738.                     itemList->Append(aItem);
  739.  
  740. //                    fSelItems->Append(aItem);
  741.                     
  742.                     hitCell.v = r.top;
  743.                     hitCell.h = 0;
  744.                     
  745.                     GetCellRect(hitCell,&pinRect);
  746.                     
  747.                     LongToQDRect(&pinRect,&cRect);
  748.                     
  749.                     aItem->GetDisplayText(text);
  750.                     indentLeft =  aItem->GetLevel()*kCellLevelIndent;
  751.  
  752.                         // Calculate the icon rectangle. It is centered
  753.                         // in the selected cell, and indeted to indentLeft.
  754.                     iRect.bottom = iRect.top =
  755.                                     (pinRect.bottom + pinRect.top) / 2 - 8;
  756.                     iRect.right = iRect.left = pinRect.left + indent.h +
  757.                                                                 indentLeft;
  758.                     iRect.right += 16;
  759.                     iRect.bottom += 16;
  760.                     
  761.                     iconRect = iRect;
  762.                     iconRect.left += 20;
  763.                     iconRect.right += 20;
  764.                     
  765.                     cRect.left = iconRect.right + 2;
  766.                     cRect.right = cRect.left + StringWidth(text);
  767.                     FrameRect(&iconRect);
  768.                     FrameRect(&cRect);
  769.                 }
  770.             }
  771.         }
  772.         CloseRgn(*rgnHdl);
  773.     }
  774.  
  775.     return itemList;
  776. }
  777.  
  778. Boolean CItemTable::HitInDrag(Cell aCell)
  779. {
  780.     return PtInRgn(aCell, itsSelection);
  781. }
  782.  
  783. /*
  784.  * DropedSameParent()
  785.  *
  786.  *    Return true if theItem parent is same parent
  787.  *    as the item in dropCell.
  788.  */
  789.  
  790. Boolean CItemTable::DropedSameParent(short dropCell, CItem *theItem)
  791. {
  792.     CItem    *parent;
  793.  
  794.     if(theItem->GetParent() == 0L)
  795.         return FALSE;
  796.  
  797.     parent = GetItem(dropCell);
  798.  
  799.     return parent == theItem->GetParent();
  800. }
  801.  
  802. Boolean CItemTable::ItemCanAcceptDrop(Cell hitCell, CItemList *selectedItems)
  803. {
  804.     CItem    *theItem;
  805.     Rect    r;
  806.  
  807.     // Send a Can Accept message to the hit Cell.
  808.     r = tableBounds;
  809.     if(PtInRect(hitCell, &r)) {
  810.         theItem = GetItem(hitCell.v + 1);
  811.         ASSERT(theItem);
  812.         return theItem->CanAccept(selectedItems);
  813.     } else
  814.         return TRUE;
  815. }
  816.  
  817. /******************************************************************************
  818.  DeselectRect
  819.  
  820.     Deselect a rectangular region of cells.
  821. ******************************************************************************/
  822.  
  823. void CItemTable::DeselectRect(Rect *deselectRect, Boolean redraw)
  824. {
  825.     Rect    realCells, r, visPixels, cellRect;
  826.     LongRect pixels;
  827.     
  828.     /* first clip selectRect to intersection with tableBounds */
  829.     
  830.     if (SectRect( deselectRect, &tableBounds, &realCells))
  831.     {
  832.         /* only deselect cells that were actually selected */
  833.         
  834.         RectRgn( gUtilRgn, &realCells);
  835.         SectRgn( itsSelection, gUtilRgn, gUtilRgn);
  836.         if (!EmptyRgn( gUtilRgn))
  837.         {
  838.             DiffRgn( itsSelection, gUtilRgn, itsSelection);
  839.             if (redraw)
  840.             {
  841.                 Prepare();
  842.                 cellRect = (**gUtilRgn).rgnBBox;
  843.                 for (r.top = cellRect.top; r.top < cellRect.bottom; r.top++)
  844.                 {
  845.                     r.bottom = r.top + 1;
  846.                     for (r.left = cellRect.left; r.left < cellRect.right; r.left++)
  847.                     {
  848.                         r.right = r.left + 1;
  849.                         if (PtInRgn( topLeft( r), gUtilRgn))
  850.                             Hilite( &r, FALSE);
  851.                     }
  852.                 }                    
  853.             }
  854.         }
  855.         
  856.         BroadcastChange( tableSelectionChanged, NULL);
  857.     }
  858.  
  859. }    /* CTable::DeselectRect */
  860.  
  861. void CItemTable::HiliteCellRegion( RgnHandle cellRgn, Boolean fHilite)
  862. {
  863.     Rect    cellRect;
  864.     Rect     r;
  865.     
  866.     if (!EmptyRgn( cellRgn))
  867.     {
  868.         cellRect = (**cellRgn).rgnBBox;
  869.         for (r.top = cellRect.top; r.top < cellRect.bottom; r.top++)
  870.         {
  871.             r.bottom = r.top + 1;
  872.             for (r.left = cellRect.left; r.left < cellRect.right; r.left++)
  873.             {
  874.                 r.right = r.left + 1;
  875.                 if (PtInRgn( topLeft( r), cellRgn))
  876.                     Hilite( &r, fHilite);
  877.             }
  878.         }                    
  879.     }
  880.  
  881. }    /* CTable::HiliteCellRegion */
  882.  
  883. void    CItemTable::ExpandCollaspeSelection(short expandColaspe)
  884. {
  885.     CItem    *aItem;
  886.     Rect    selectRect;
  887.     Cell    theCell;
  888.     short    i,n;
  889.     
  890.     theCell.h = 0;
  891.     
  892.     selectRect = (**itsSelection).rgnBBox;
  893.     fSelItems->DeleteItems();
  894.     theCell.v = selectRect.top;
  895.     for(theCell.v = 0;theCell.v < bounds.bottom;theCell.v++) {
  896.         if(PtInRgn(theCell,itsSelection)) {
  897.             aItem = GetItem(theCell.v + 1);
  898.             if(aItem && ((aItem->GetExpanded() == 0 && expandColaspe) ||
  899.                           aItem->GetExpanded() && expandColaspe == 0)) {
  900.                 aItem->SetExpanded(expandColaspe);
  901.                 fSelItems->Append(aItem);
  902.             }
  903.         }
  904.     }
  905.     n = fSelItems->GetNumItems();
  906.     while(n > 0) {
  907.         aItem = (CItem*) fSelItems->FirstItem();
  908.         theCell.v = ((CItemList*)itsArray)->Offset(aItem);
  909.         AnimateOpenClose(theCell);
  910.         ExpandCell(theCell,expandColaspe);
  911.         fSelItems->DeleteItem(1);
  912.         n--;
  913.     }
  914.     selectRect.bottom = selectRect.top +1;
  915.     selectRect.right = selectRect.left +1;
  916.     RectRgn(itsSelection,&selectRect);
  917. }
  918.  
  919. void CItemTable::DoKeyDown(char theChar, Byte keyCode, EventRecord *macEvent)
  920. {
  921.     
  922.     switch(theChar) {
  923.         case deleteKey:
  924.             DeleteSelectedItems();
  925.             break;
  926.         default:
  927.             if(isprint(theChar))
  928.                 DoTyping(theChar);
  929.             else if(keyCode == KeyLeftCursor && 
  930.                     (macEvent->modifiers & cmdKey)) // Close the Selected Cell
  931.                 ExpandCollaspeSelection(0);
  932.             else if(keyCode == KeyRightCursor && 
  933.                     (macEvent->modifiers & cmdKey)) // Open the Selected Cell
  934.                 ExpandCollaspeSelection(1);
  935.             else
  936.                 inherited::DoKeyDown(theChar, keyCode, macEvent);
  937.             break;
  938.     }
  939. }
  940.  
  941. void CItemTable::DoTyping(char theChar)
  942. {
  943.     CTypingTask    *aTask;
  944.  
  945.     if(fTypingTask && !fTypingTask->CanStillType()) {
  946.  
  947.             // Throw the task away if too much time has passed...
  948.         ForgetObject(fTypingTask);
  949.  
  950.     }
  951.  
  952.     if(!fTypingTask) {
  953.  
  954.         aTask = new CTypingTask;
  955.         aTask->ITypingTask(this, 128);
  956.         fTypingTask = aTask;
  957. //        Notify(aTask);
  958.     } else
  959.         aTask = fTypingTask;
  960.  
  961.     aTask->DoTyping(theChar);
  962. }
  963.  
  964. #include <string.h>
  965.  
  966. Boolean    Find_First(CObject *theItem, long buff);        /* (CItem *, char *) */
  967.  
  968. Boolean Find_First(CObject *theItem, long buff)
  969. {
  970.     CItem    *i = (CItem *) theItem;
  971.     char str[128], *b = (char *) buff;
  972.  
  973.     short j, end;
  974.  
  975.     i->GetDisplayText(str);
  976.     
  977.     end = b[0] < str[0] ? b[0] : str[0];
  978.     for(j = 1; j <= end; j++)
  979.         if(b[j] != tolower(str[j]))
  980.             return FALSE;
  981.  
  982.     return TRUE;
  983. }
  984.  
  985. void CItemTable::SelectMatchingText(char *buff)
  986. {
  987.     CItem        *matchItem;
  988.     CItemList    *aList;
  989.     
  990.     ASSERT(itsArray);
  991.     
  992.     aList = (CItemList *) itsArray;
  993.  
  994.     matchItem = 0L;    
  995.     matchItem = (CItem *) aList->FirstSuccess1(Find_First, (long) buff);
  996.  
  997.     if(matchItem) {
  998.  
  999.         Cell    hCell = {0, 0};
  1000.         long    i = aList->FindIndex(matchItem);
  1001.  
  1002.         hCell.v = i - 1;
  1003.         SelectCell(hCell, FALSE, TRUE);
  1004.     }
  1005. }
  1006.  
  1007. void CItemTable::DeleteSelectedItems(void)
  1008. {
  1009.     CItem    *anItem, *parent;
  1010.     Rect    selItems = (**itsSelection).rgnBBox;
  1011.     long    i;
  1012.  
  1013.     ASSERT(itsArray && member( itsArray, CItemList));
  1014.  
  1015.     for(i = selItems.top; i < selItems.bottom; i++) {
  1016.             // First remove the subview from the parent
  1017.         anItem = GetItem((short) i + 1);
  1018.         parent = anItem->GetParent();
  1019.     
  1020.         if(parent)
  1021.             parent->RemoveSubItem(anItem);
  1022.     
  1023.             // Now delete the item from the list
  1024.         itsArray->DeleteItem(i + 1);
  1025.         BroadcastChange(itemTableItemRemoved, 0);
  1026.         
  1027.         anItem->Dispose();
  1028.     }
  1029. }
  1030.  
  1031. void CItemTable::GetCellRect(Cell theCell, register LongRect *cellRect)
  1032. {
  1033.     CItem    *aItem;
  1034.     char    text[256];
  1035.     short    indentLevel;
  1036.     
  1037.     inherited::GetCellRect(theCell,cellRect);
  1038.     return;
  1039.     if ( PtInRect( theCell, &tableBounds)) {
  1040.         aItem = GetItem(theCell.v + 1);
  1041.         if(aItem == 0)
  1042.             return;
  1043.         aItem->GetDisplayText(text);
  1044.         if(aItem) {
  1045.             width = StringWidth(text) + kCellLevelIndent;
  1046.             indentLevel = 20 + aItem->GetLevel() * kCellLevelIndent;
  1047.             cellRect->right = cellRect->left = indentLevel;
  1048.             cellRect->right += width;
  1049.         }
  1050.     }
  1051.     
  1052. }    /* CTable::GetCellRect */
  1053.  
  1054.  
  1055. void CItemTable::CreateTextEnvironment( void)
  1056. {
  1057.     CTextEnvirons *textEnvirons;
  1058.     TextInfoRec    textInfo;
  1059.  
  1060.     textEnvirons = new( CTextEnvirons);
  1061.     itsEnvironment = textEnvirons;
  1062.     textEnvirons->ITextEnvirons();
  1063.     
  1064.     textInfo.fontNumber = kCellFont;
  1065.     textInfo.theSize = kCellFontSize;
  1066.     textInfo.theStyle = kCellFontStyle;
  1067.     textInfo.theMode = srcOr;
  1068.     
  1069.     textEnvirons->SetTextInfo( &textInfo);
  1070.  
  1071. }    /* CTable::CreateTextEnvironment */
  1072.